#include "mod_rfcard.h"

#include "platform.h"
#include "usart.h"
#include "crc16.h"
#include <stdlib.h>
#include <string.h>

#define RFCARD_CMD_LEN_MAX (16u)
#define MAX_FLAG (10u)
    
enum RFCARD_ALARM{
    E_RFCARD_ALARM_OFF = 0u,
    E_RFCARD_ALARM_ON
};

enum E_RF_CMD_TYPE {
    RF_CMD_CLOSE_TYPE_A_RF = 0,
    RF_CMD_OPEN_TYPE_A_RF,
    RF_CMD_SEARCH_TYPE_A_CARD,
    RF_CMD_GET_PARA_1,
    RF_CMD_GET_PARA_2,
    RF_CMD_GET_PARA_3,
    RF_CMD_SET_BEZZER,
    RF_CMD_END
};

typedef struct T_RFCardRevMsg{ 
    uint8_t msgId;
    uint8_t serialNum;
    uint8_t dataLen;
    uint8_t buf[100];
} T_RFCardRevMsg;

typedef struct T_RfCardParse {
    uint8_t state;
    uint8_t cnt;
    uint16_t crc;
    uint8_t rcrc[2];
    T_RFCardRevMsg val;
}T_RfCardParse;

typedef struct T_RFCard{
    enum E_RF_CMD_TYPE cmdTypeSend;
    uint8_t serialNum;
    uint8_t cmdAckTimeoutNum;
    uint8_t no_ack_cnt;
    uint8_t rfcardalarm;
    enum RfcardState enable;
    uint8_t alarmStateTmp;
	char_t cardSn[20];
	uint8_t isSwipCard;
    T_RfCardParse rfp; 

}T_RFCard;

static struct T_RFCard rfcard;

static const uint8_t g_RfCardCmd[RF_CMD_END][RFCARD_CMD_LEN_MAX] = {
    {0x06u, 0xFFu, 0x0Fu, 0xA2u, 0x00u, 0x40u, 0xC9u,  0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u}, /* close Type A */
    {0x06u, 0xFFu, 0x10u, 0xA1u, 0x00u, 0xCBu, 0x46u,  0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u}, /* open Type A */
    {0x06u, 0xFFu, 0x11u, 0xA3u, 0x00u, 0xC7u, 0x52u,  0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u}, /* search Type A card */
    {0x0du, 0xFFu, 0x12u, 0xA9u, 0x07u, 0x00u, 0xA4u, 0x00u, 0x00u, 0x02u, 0x3Fu, 0x00u, 0x36u, 0x4Cu,  0x00u, 0x00u}, /* chg data:card serian */
    {0x0du, 0xFFu, 0x13u, 0xA9u, 0x07u, 0x00u, 0xA4u, 0x00u, 0x00u, 0x02u, 0xDFu, 0x02u, 0x16u, 0x52u,  0x00u, 0x00u}, /* chg data:0xDF, 0x01 普天卡 0xDF, 0x02 广天川卡 */
    {0x0bu, 0xFFu, 0x14u, 0xA9u, 0x05u, 0x00u, 0xB0u, 0x95u, 0x00u, 0x2Au, 0x42u, 0x06u,  0x00u, 0x00u, 0x00u, 0x00u}, /* chg data:card num Balance */
    {0x08u, 0xFFu, 0x15u, 0x62u, 0x02u, 0x01u, 0x01u, 0x80u, 0x0Cu,  0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u}, /* bezzer */
};

static uint8_t RFCard_GetCmdLen(enum E_RF_CMD_TYPE cmdType) {
    return g_RfCardCmd[cmdType][0];
}

static void RFCard_GetCmdData(enum E_RF_CMD_TYPE cmdType, uint8_t *buf) {
    memcpy(buf, &g_RfCardCmd[cmdType][1], (uint32_t)g_RfCardCmd[cmdType][0]);
}

static void GetCardNo(const uint8_t *buf, uint8_t *cardNo){
	int32_t i,j=0;
    for (i = 15 - 4; i < (23 - 4); i++) {
        uint8_t value = buf[i];
        cardNo[j] = (uint8_t)((value >> 4u) + 0x30u);
        cardNo[j + 1] = (uint8_t)((value & 0x0fu) + 0x30u);
        j += 2;
    }
}

static void rfcard_deal_recv(T_RFCard *rfc, const T_RFCardRevMsg *msg){
    
#if 0
    printf("rfc send:%d (%d)rec:", rfc->cmdTypeSend, msg->dataLen);
    for(uint8_t i = 0; i < msg->dataLen; i++) {
        printf("%02x", msg->buf[i]);
    }
    printf("\r\n");
#endif
    
    rfc->no_ack_cnt = 0u;
    
    switch (rfc->cmdTypeSend) {
    case RF_CMD_CLOSE_TYPE_A_RF:
        if ((msg->msgId == (uint8_t)0xa2) && (msg->buf[0] == (uint8_t)0)) {
            rfc->cmdTypeSend = RF_CMD_OPEN_TYPE_A_RF;
            rfc->cmdAckTimeoutNum = 0u;
        }else{
            rfc->cmdTypeSend = RF_CMD_CLOSE_TYPE_A_RF;
        }
        break;
    case RF_CMD_OPEN_TYPE_A_RF:
        if ((msg->msgId == (uint8_t)0xa1) && (msg->buf[0] == (uint8_t)0)) {
            rfc->cmdTypeSend = RF_CMD_SEARCH_TYPE_A_CARD;
        }else{
            rfc->cmdTypeSend = RF_CMD_CLOSE_TYPE_A_RF;
        }
        break;
    case RF_CMD_SEARCH_TYPE_A_CARD:
        if ((msg->msgId == (uint8_t)0xa3) && (msg->buf[0] == (uint8_t)0)) {
            rfc->cmdTypeSend = RF_CMD_GET_PARA_1;
        }else{
            rfc->cmdTypeSend = RF_CMD_CLOSE_TYPE_A_RF;
        }
        break;
    case RF_CMD_GET_PARA_1:
        if (msg->msgId == (uint8_t)0xa9) {
            rfc->cmdTypeSend = RF_CMD_GET_PARA_2;
        }else{
            rfc->cmdTypeSend = RF_CMD_CLOSE_TYPE_A_RF;
        }
        break;
    case RF_CMD_GET_PARA_2:
        if (msg->msgId == (uint8_t)0xa9) {
            rfc->cmdTypeSend = RF_CMD_GET_PARA_3;
        }else{
            rfc->cmdTypeSend = RF_CMD_CLOSE_TYPE_A_RF;
        }
        break;
    case RF_CMD_GET_PARA_3:
        if (msg->msgId == (uint8_t)0xa9) {
            uint8_t cardNo[17] = {0u};
            
            if ((msg->buf[0] == (uint8_t)0xe5) || (msg->dataLen != (uint8_t)45)) {
                rfc->cmdTypeSend = RF_CMD_CLOSE_TYPE_A_RF;
                break;
            }
            
            GetCardNo(msg->buf, cardNo);
            #if 1
            if (memcmp(cardNo,"63", 2u) != 0){
                rfc->cmdTypeSend = RF_CMD_CLOSE_TYPE_A_RF;
                break;                    
            }
            #endif

            if ((cardNo[0] == 0x30u) && (cardNo[2] == 0x30u)) {
                rfc->cmdTypeSend = RF_CMD_CLOSE_TYPE_A_RF;
                break;
            } 
            
            if (rfc->enable == RFCARD_DISABLE) {
                printf("get card sn(no used):%s\r\n", cardNo);
                rfc->cmdTypeSend = RF_CMD_CLOSE_TYPE_A_RF;
                break;
            }
            printf("get card sn:%s\r\n", cardNo);
            memcpy(rfc->cardSn, cardNo, sizeof(cardNo));
            rfc->isSwipCard = 1u;

            rfc->cmdTypeSend = RF_CMD_SET_BEZZER;        
        }else{
            rfc->cmdTypeSend = RF_CMD_CLOSE_TYPE_A_RF;
        }
        break;
    case RF_CMD_SET_BEZZER:
        /* if (msg->msgId == 0x62) {} */
        os_msleep(1000u);
        rfc->isSwipCard = 0u;  /* 延迟1s后删除读取的卡信息 */
        rfc->cmdTypeSend = RF_CMD_CLOSE_TYPE_A_RF;
        break;
    case RF_CMD_END: /* pclint 788 */
        break;
    default:
        rfc->cmdTypeSend = RF_CMD_CLOSE_TYPE_A_RF;
        rfc->isSwipCard = 0u; 
        break;
    }
    
    
}

static void RFCard_Parse(T_RFCard *rfc, uint8_t val) {
    
    switch(rfc->rfp.state){
        case 0: /* head 0xff */
            if (val == (uint8_t)0xff){
                rfc->rfp.state++;
                rfc->rfp.crc = (uint16_t)0xffff;
                rfc->rfp.crc = Crc16(rfc->rfp.crc, &val, 1);
            }
        break;
        case 1: /* tag */
            rfc->rfp.state++;
            rfc->rfp.val.serialNum = val;
            rfc->rfp.crc = Crc16(rfc->rfp.crc, &val, 1);
        break;
        case 2: /* cmd */
            rfc->rfp.state++;
            rfc->rfp.val.msgId = val;
            rfc->rfp.crc = Crc16(rfc->rfp.crc, &val, 1);
        break;
        case 3: /* len */
            if (val < sizeof(rfc->rfp.val.buf)){
                rfc->rfp.state++;
                rfc->rfp.val.dataLen = val;
                rfc->rfp.crc = Crc16(rfc->rfp.crc, &val, 1);
            }else{
                memset(&rfc->rfp, 0, sizeof(T_RfCardParse));
            }
        break;    
        case 4: /* data */
            rfc->rfp.val.buf[rfc->rfp.cnt] = val;
            rfc->rfp.crc = Crc16(rfc->rfp.crc, &val, 1);
            rfc->rfp.cnt++;
            if (rfc->rfp.cnt >= rfc->rfp.val.dataLen) {
                rfc->rfp.state++;
            }
        break;
        case 5: /* crcH */
           rfc->rfp.rcrc[0] = val;
           rfc->rfp.state++; 
        break;
        case 6: /* crcL */
        {
            uint16_t rcrc;
            rfc->rfp.rcrc[1] = val;
            rcrc = (uint16_t)((uint16_t)((uint16_t)rfc->rfp.rcrc[0] << 8u) + rfc->rfp.rcrc[1]);
            if (rcrc == rfc->rfp.crc) {
                rfcard_deal_recv(rfc, &rfc->rfp.val); /* 接收到完整命令，进行解析 */
            }
            memset(&rfc->rfp, 0, sizeof(T_RfCardParse));
        }
        break;
        default:
            memset(&rfc->rfp, 0, sizeof(T_RfCardParse));
        break;
    }
}

static void  RFCard_CheckRfcardFlag(T_RFCard *rfc) {
    if (rfc->no_ack_cnt >= MAX_FLAG){
        rfc->no_ack_cnt = MAX_FLAG;
        if (rfc->rfcardalarm != (uint8_t)E_RFCARD_ALARM_ON){
            rfc->rfcardalarm = (uint8_t)E_RFCARD_ALARM_ON;
            rfc->cmdTypeSend = RF_CMD_CLOSE_TYPE_A_RF;
        }
    }else{
        if (rfc->rfcardalarm != (uint8_t)E_RFCARD_ALARM_OFF){
            rfc->rfcardalarm = (uint8_t)E_RFCARD_ALARM_OFF;
        }
    }
}

static void RFCard_SendCmd(T_RFCard *rfc) {
    uint8_t cmdLen;
    uint16_t crc;
    uint8_t cmdData[RFCARD_CMD_LEN_MAX] = {0u};
    
    rfc->serialNum++;
    rfc->no_ack_cnt++;

    cmdLen = RFCard_GetCmdLen(rfc->cmdTypeSend);
    
    RFCard_GetCmdData(rfc->cmdTypeSend, cmdData);
    cmdData[1] = rfc->serialNum;
    crc = Crc16((uint16_t)0xffff, cmdData, ((int32_t)cmdLen - 2));
    cmdData[cmdLen - 2u] = (uint8_t)(((uint16_t)crc >> 8u) & (uint16_t)0x00ff);
    cmdData[cmdLen - 1u] = (uint8_t)((uint16_t)crc & (uint16_t)0x00ff);
    
    usart6_send(cmdData, (uint32_t)cmdLen);
}

static void RFCard_RecvCmd(T_RFCard *rfc) {
    uint8_t data;

    while(usart6_receive(&data)){
       RFCard_Parse(rfc, data);
    }
}

static void rfcard_task(void *para) {
    para = para;
    
    /*lint -e(716) */
	while(1){
		RFCard_SendCmd(&rfcard);
		os_msleep(20u);
		RFCard_RecvCmd(&rfcard);
		RFCard_CheckRfcardFlag(&rfcard);	
	}
}

int32_t rfcard_read(char_t *id){
	int32_t ret = 0;
	if (rfcard.isSwipCard){
		memcpy(id, rfcard.cardSn, strlen(rfcard.cardSn));
		rfcard.isSwipCard = 0u;
		ret = 1;
	}
	return ret;
}

void rfcard_set(enum RfcardState state){
    if (rfcard.enable != state) {
        rfcard.enable = state;
    }
}

int32_t rfcard_isalarm(void){
	return (rfcard.rfcardalarm == (uint8_t)E_RFCARD_ALARM_ON);
}

int32_t rfcard_init(void){
    int32_t ret = 0;
    os_pthread_t rfcard_thread;
    memset(&rfcard, 0, sizeof(rfcard));
    rfcard.cmdTypeSend = RF_CMD_CLOSE_TYPE_A_RF;
    rfcard.serialNum = 0u;
    rfcard.cmdAckTimeoutNum = 0u;
    rfcard.no_ack_cnt = 0u;
    rfcard.rfcardalarm = (uint8_t)E_RFCARD_ALARM_OFF;
    rfcard.enable = RFCARD_DISABLE;
    rfcard.alarmStateTmp = (uint8_t)E_RFCARD_ALARM_OFF;
	rfcard.isSwipCard = 0u;
    
	usart6_init(115200u);

    if (os_pthread_create("rfcard", &rfcard_thread, rfcard_task,  NULL, OS_TASK_PRIO_NOMAL, OS_STACK_SIZE_MEDIUM) != 0){
		ret = -1;
	}
    
    return ret;	
}




